package timeDemo;


import org.apache.log4j.Logger;
import org.junit.Test;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

//import com.sun.org.apache.bcel.internal.classfile.InnerClass;
//import com.sun.org.apache.bcel.internal.generic.NEW;

/**
 * Created by 张英杰 on 2015/10/23.
 * TODO calendar.get(Calendar.MONTH) 月份是从0—11  比真实月份少了一个月
 */
public class TimeUtils {
    private static final Logger logger = Logger.getLogger(TimeUtils.class);
    private static final String CRON_DATE_FORMAT = "ss mm HH dd MM ? yyyy";



    public static void main(String[] args) {
        logger.info("main: ");

        // 给定时间戳 (毫秒)
//        long timestamp = 1726053550135L;
//        long timestamp = 1726039696322L;
//        long timestamp = 1725975250144L;
//        long timestamp = 1725972789868L;
//        long timestamp = 1725970330118L;
//        long timestamp = 1725971470122L;
//        long timestamp = 1726124290136L;
//        long timestamp = 1726136410113L;
//        long timestamp = 1726149070096L;
//        long timestamp = 1725912054820L;
        long timestamp = 1726206617112L;


        // 加8小时转换为东八区时间戳 (毫秒)
        long eastEightTimestamp = timestamp;

        // 格式化为日期时间 (东八区)
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        String formattedTime = formatter.format(new Date(eastEightTimestamp));

        // 输出结果
        System.out.println("东八区格式化时间: " + formattedTime);

        long start = System.currentTimeMillis();

        System.err.println("TimeUtils:cost:"+(System.currentTimeMillis()-start));
    }



    private static void testSpeed() {
        long start = System.currentTimeMillis();
        for (int i = 0; i < 100_000; i++) {
            getNowMillisForFile2();
        }
        System.out.println("TimeUtils:main1:"+(System.currentTimeMillis()-start));//321ms 只差 5 倍。
        long start2 = System.currentTimeMillis();
        for (int i = 0; i < 100_000; i++) {
            getNowMillisForFileZone8();
        }
        System.out.println("TimeUtils:main2:"+(System.currentTimeMillis()-start2));//60ms
    }
    //使用这个，避免了 时区问题。也没有那么慢。10万 250-330 ms.
    public static String getNowMillisForFile2() {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss_SSS");
        Date date = new Date(System.currentTimeMillis());
        return dateFormat.format(date);
    }
    //东八区，时差.. 比SimpleDateFormat 快 4倍。消耗都很小。
    public static String getNowMillisForFileZone8() {
        return getNowMillisForFile(8);
    }
    public static String getNowMillisForFile(int timeZone) {
        long currentTimeMillis = System.currentTimeMillis();

        // 东八区与UTC的时差是8小时，转换为毫秒是8 * 60 * 60 * 1000
//        long offset = 8 * 60 * 60 * 1000;
        long offset = timeZone * 60 * 60 * 1000;
        long localTimeMillis = currentTimeMillis + offset;

        // 使用公历算法计算年、月、日、小时、分钟、秒和毫秒
        long millisInDay = 24 * 60 * 60 * 1000;
        long daysSinceEpoch = localTimeMillis / millisInDay;

        // 从1970年1月1日起的天数
        long remainingMillis = localTimeMillis % millisInDay;

        // 计算小时、分钟、秒和毫秒
        int hours = (int) (remainingMillis / (1000 * 60 * 60));
        int minutes = (int) ((remainingMillis / (1000 * 60)) % 60);
        int seconds = (int) ((remainingMillis / 1000) % 60);
        int milliseconds = (int) (remainingMillis % 1000);

        // 设置基准日期为1970年1月1日
        int year = 1970;
        int month = 0;
        int day = 1;

        // 计算每年的天数
        while (daysSinceEpoch >= daysInYear(year)) {
            daysSinceEpoch -= daysInYear(year);
            year++;
        }

        // 计算每月的天数
        int[] daysInMonths = {31, isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        while (daysSinceEpoch >= daysInMonths[month]) {
            daysSinceEpoch -= daysInMonths[month];
            month++;
        }
        day += daysSinceEpoch;

        // 构建时间字符串
        StringBuilder sb = new StringBuilder();

        // 年
        sb.append(year).append("_");

        // 月
        if (month + 1 < 10) sb.append("0");
        sb.append(month + 1).append("_");

        // 日
        if (day < 10) sb.append("0");
        sb.append(day).append("_");

        // 时
        if (hours < 10) sb.append("0");
        sb.append(hours).append("_");

        // 分
        if (minutes < 10) sb.append("0");
        sb.append(minutes).append("_");

        // 秒
        if (seconds < 10) sb.append("0");
        sb.append(seconds).append("_");

        // 毫秒（需要三位数）
        if (milliseconds < 100) sb.append("0");
        if (milliseconds < 10) sb.append("0");
        sb.append(milliseconds);

        return sb.toString();
    }
    // 判断是否为闰年
    private static boolean isLeapYear(int year) {
        return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
    }
    // 计算一年的天数
    private static int daysInYear(int year) {
        return isLeapYear(year) ? 366 : 365;
    }

    //日志调用， 高频，快速。--东 8 区。 eg: 09:45:12.504
    public static String getNowMillis(){
        long currentTimeMillis = System.currentTimeMillis();

        // 东八区与UTC的时差是8小时，转换为毫秒是8 * 60 * 60 * 1000
        long offset = 8 * 60 * 60 * 1000;
        long localTimeMillis = currentTimeMillis + offset;

        // 计算小时、分钟、秒和毫秒
        int hours = (int) ((localTimeMillis / (1000 * 60 * 60)) % 24);
        int minutes = (int) ((localTimeMillis / (1000 * 60)) % 60);
        int seconds = (int) ((localTimeMillis / 1000) % 60);
        int milliseconds = (int) (localTimeMillis % 1000);

        // 构建时间字符串
        StringBuilder sb = new StringBuilder();

        // 时
        if (hours < 10) sb.append("0");
        sb.append(hours).append(":");

        // 分
        if (minutes < 10) sb.append("0");
        sb.append(minutes).append(":");

        // 秒
        if (seconds < 10) sb.append("0");
        sb.append(seconds).append(".");

        // 毫秒（需要三位数）
        if (milliseconds < 100) sb.append("0");
        if (milliseconds < 10) sb.append("0");
        sb.append(milliseconds);

        return sb.toString();
    }
    //国际化
    public void testGlobalFormat() {
        System.out.println("testGlobalFormat:");
        String format = new SimpleDateFormat(CRON_DATE_FORMAT).format(new Date());//结果：40 33 16 06 12 ? 2022
        logger.info("testGlobalFormat: result:" + format);//

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd 我的自定义数据");// 可以从 new date 可以得出数据
//      SimpleDateFormat sdf = new SimpleDateFormat("aaaa Année MM Mois dd Jour");//Illegal pattern character 'A' ,A占用了
        Date date = null;
        try {
            date = sdf.parse("2020.07.08");
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("TimeUtils:testGlobalFormat:" + sdf.format(new Date()));
        logger.info("compareTest: " + date);
    }

    public static void testCalendar() {
        // long testDate = System.currentTimeMillis();
        long testDate = 1640946984000L;
        Date date = new Date(testDate);
        System.out.println("TimeUtils:testCalendar:" + date);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        //测试
        //2021-04-02 18:32:02,791
        System.out.println("date.getYear()==" + date.getYear() + "    " + calendar.get(Calendar.YEAR));//121    2021
        System.out.println("date.getMonth==" + date.getMonth() + "    " + calendar.get(Calendar.MONTH));//3    3  TODO 都错了，月份是从0—11  cal.get(Calendar.MONTH)比真实月份少了一个月
        System.out.println("date.getDay()==" + date.getDay() + "    " + calendar.get(Calendar.DAY_OF_MONTH));//5    2 TODO date 出错。
        System.out.println("date.getHours()==" + date.getHours() + "    " + calendar.get(Calendar.HOUR_OF_DAY));//18    18
        System.out.println("date.getMinutes()==" + date.getMinutes() + "    " + calendar.get(Calendar.MINUTE));//32    32
        System.out.println("date.getSeconds()==" + date.getSeconds() + "    " + calendar.get(Calendar.SECOND));//2    2

        System.out.println("dayOfMonth method  ==" + getDayOfMonth(testDate));
    }

    @Test
    public void formatHourMin() {
//      String mNewtime = "12:01";
        String mNewtime = "00:00";
        //24Hour
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm", Locale.getDefault());
        try {
            Date date = sdf.parse(mNewtime);
            logger.info("formatHourMin: date:" + date);//Thu Jan 01 12:01:00 CST 1970
            int hours = date.getHours();
            int minutes = date.getMinutes();
            logger.info("formatHourMin: hours:" + hours + "  min:" + minutes);
            String startTime = sdf.format(date);
            logger.info("formatHourMin: startTime: " + startTime);//12:01


            Calendar calendar = Calendar.getInstance();
            calendar.set(calendar.HOUR_OF_DAY, hours);
            calendar.set(calendar.MINUTE, minutes);
            logger.info("formatHourMin: calendar: " + calendar.getTime() + " " + calendar.getTimeInMillis());//Sat Oct 31 12:01:42 CST 2020
            Date nowDate = new Date();
            nowDate.setHours(hours);
            nowDate.setMinutes(minutes);
            logger.info("formatHourMin: date:" + nowDate + "  " + nowDate.getTime());//Sat Oct 31 12:01:42 CST 2020


            long tempNow = System.currentTimeMillis() + 1000 * 3600 * 2680;

            logger.info("formatHourMin: tempNow-----> " + new Date(tempNow));


            while (calendar.getTimeInMillis() - tempNow < 0) {
                calendar.add(Calendar.DATE, 1);
                logger.info("formatHourMin: add calendartime:" + calendar.getTime());
            }

            logger.info("formatHourMin: over----> calendartime:" + calendar.getTime());


        } catch (ParseException e) {
            e.printStackTrace();
        }

    }

    @Test
    public void millis2Date() {
//      Date date = new Date(1594793211818L);
//      logger.info("date  "+date);

//      Date date2 = new Date(1594794512183L);//14:28:32
        Date date2 = new Date(1594877253805L);// start 11:06:26
        logger.info("date start :" + date2);
//      Date date2 = new Date(1594795092419L);//14:38:12
//      Date date2 = new Date(1594797064257L);//record 15:11 4ed4a1c275dc43b9868abbe1b80e5e99
//      Date daterecord = new Date(1594877246160L);//record 16:22:31
        Date daterecord = new Date(1594878922192L);//record 16:22:31
        logger.info("date record: " + daterecord);

        logger.info("isneed up: " + (daterecord.getTime() > date2.getTime()));
    }


    //Thu Jan 01 08:00:00 CST 1970
    @Test
    public void pcStartTime() {
        Date date = new Date(0);
        logger.info("pcStartTime: " + date);
        logger.info("pcStartTime: " + date.getTime());
    }

    @Test
    public void compareTest() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd");
        Date date = null;
        try {
            date = sdf.parse("2020.07.08");
        } catch (ParseException e) {
            e.printStackTrace();
        }
        logger.info("compareTest: " + date);
        logger.info("compareTest:long: " + date.getTime());
        Date preset = new Date();
        logger.info("compareTest: preset " + preset);
        int i = date.compareTo(preset);
        System.out.println("result:" + i);
    }

    /**
     * 返回当前时间
     *
     * @return
     */
    public static int getCurrentYear() {
        Date date = new Date();
        SimpleDateFormat format = new SimpleDateFormat("yyyy");
        return Integer.parseInt(format.format(date));
    }

    /**
     * 返回当前时间
     *
     * @return
     */
    public static String getCurrentDay() {
        Date date = new Date();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        return format.format(date);
    }

    /**
     * 返回当前时间
     *
     * @return
     */
    public static String getDayOfMonth(long mils) {
        Date date = new Date(mils);
        SimpleDateFormat format = new SimpleDateFormat("dd");
        return format.format(date);
    }

    /**
     * 返回当前时间
     *
     * @return
     */
    public static String getCurrentTime() {
        Date date = new Date();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return format.format(date);
    }

    /**
     * 返回当前时间
     *
     * @return
     */
    public static String getCurrentTimeMills() {
        Date date = new Date();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss-sss");
        return format.format(date);
    }

    //返回当前时间 用于保存文件，有点手机不支持空格 ：等
    public static String getTakePhotoTime() {
        Date date = new Date();
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd-HHmmss");
        return format.format(date);
    }

    /**
     * 传入时间返回年份
     *
     * @return
     */
    public static String formatYear() {
        Date date = new Date();
        SimpleDateFormat format = new SimpleDateFormat("yyyy");
        return format.format(date);
    }

    /**
     * 传入时间返回月份
     *
     * @param date
     * @return
     */
    public static String formatMonth(Date date) {
        SimpleDateFormat format = new SimpleDateFormat("MM");
        return format.format(date);
    }

    /**
     * 传入时间返回月份
     *
     * @param date
     * @return
     */
    public static String formatSecond(Date date) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return format.format(date);
    }

    /**
     * 由任务编号得到时间
     * 输入yyyyMMddHHmmss
     * 得到yyyy-MM-dd HH:mm:ss
     *
     * @param str
     * @return
     */
    public static String getDateForDay(String str) {
        if (str.length() > 10) {
            Date d = null;
            DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            try {
                d = format.parse(str);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            SimpleDateFormat format2 = new SimpleDateFormat("yyyy-MM-dd");
            return format2.format(d);
        } else {
            return str;
        }
    }

    public static int getHour(Long millis) {
        Calendar instance = Calendar.getInstance();
        instance.setTimeInMillis(millis);
        return instance.get(Calendar.HOUR_OF_DAY);
    }


    /**
     * 返回一周前时间
     *
     * @return
     */
    public static String getDayWeekAgo() {
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.WEEK_OF_MONTH, -1);
        Date date = instance.getTime();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        return format.format(date);
    }

    public static Long ConvertDateToLong(String strDate) throws ParseException {

        if (strDate.length() == 13) {
            return Long.parseLong(strDate);
        }
        if ("-1".equals(strDate)) {
            return 0L;
        }
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        Date d = format.parse(strDate);
        return d.getTime();
    }
}
